import { AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup, ValidatorFn } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { EzFormComponent } from '../ez-form';
import { EzFormControlComponent, EzFormControlConfiguration } from '../ez-form-control';
import { EzFormGroupComponent } from '../ez-form-group';
import { EzFormConfigurationValidator, EzFormValidatorFn } from '../../utils';

@Component({
  selector: 'ez-form-item',
  templateUrl: './ez-form-item.component.html',
  styleUrls: ['./ez-form-item.component.less'],
})
export class EzFormItemComponent implements OnInit, OnDestroy, AfterViewInit {
  @Input()
  ezFormItemConfiguration: EzFormControlConfiguration;

  @Input()
  group: FormGroup;

  @ViewChild(EzFormControlComponent, { static: false })
  ezFormControl: EzFormControlComponent;

  control: FormControl;

  private destroy$ = new Subject<any>();

  constructor(public ezForm: EzFormComponent, public ezFormGroup: EzFormGroupComponent) {}

  ngOnInit(): void {
    this.checkConfiguration(this.ezFormItemConfiguration);
    this.control = new FormControl(
      {
        disabled: this.ezFormItemConfiguration.disabled,
        value: this.ezFormItemConfiguration.value,
      },
      this.parseValidators(this.ezFormItemConfiguration.validators)
    );
    if (this.ezFormItemConfiguration.onChange) {
      this.control.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
        if (this.ezFormItemConfiguration.value !== value) {
          this.ezFormItemConfiguration.onChange(this.ezFormControl, this.ezFormGroup, this.ezForm);
        }
        this.ezFormItemConfiguration.value = value;
      });
    }
    this.group.addControl(this.ezFormItemConfiguration.name, this.control);
  }

  ngAfterViewInit(): void {
    this.ezFormGroup.addEzFormControlComponent(this.ezFormItemConfiguration.name, this.ezFormControl);
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
    this.group.removeControl(this.ezFormItemConfiguration.name);
    this.ezFormGroup.removeEzFormControlComponent(this.ezFormItemConfiguration.name);
  }

  private checkConfiguration(config: EzFormControlConfiguration): void {
    EzFormConfigurationValidator.validateControl(config);
  }

  private parseValidators(validators: EzFormValidatorFn[]): ValidatorFn[] {
    const array: ValidatorFn[] = [];
    if (validators) {
      validators.forEach(fn => {
        array.push(control => {
          if (this.ezFormControl && this.ezForm.initialized) {
            return fn(this.ezFormControl, this.ezFormGroup, this.ezForm);
          }
          return null;
        });
      });
    }
    return array;
  }

  getErrorTip(): string {
    if (!this.control.errors) {
      return '';
    }
    if (this.control.errors.required) {
      return `${this.ezFormItemConfiguration.label}必填`;
    }
    return this.control.errors[Object.keys(this.control.errors)[0]];
  }

  getItemLabelSpan(): number {
    if (
      this.ezForm.ezFormConfiguration.layout === 'horizontal' ||
      this.ezForm.ezFormConfiguration.layout === 'inline'
    ) {
      if (this.ezFormItemConfiguration.itemLabelSpan || this.ezFormItemConfiguration.itemLabelSpan === 0) {
        return this.ezFormItemConfiguration.itemLabelSpan;
      } else if (this.ezForm.ezFormConfiguration.itemLabelSpan || this.ezForm.ezFormConfiguration.itemLabelSpan === 0) {
        return this.ezForm.ezFormConfiguration.itemLabelSpan;
      }
      return 6;
    } else {
      return 24;
    }
  }

  getItemControlSpan(): number {
    if (
      this.ezForm.ezFormConfiguration.layout === 'horizontal' ||
      this.ezForm.ezFormConfiguration.layout === 'inline'
    ) {
      return 24 - this.getItemLabelSpan();
    }
    return 24;
  }
}
